package com.basics.api.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.basics.api.enums.organization.GroupPermissionEnum;
import com.basics.api.enums.socket.MessageEnum;
import com.basics.api.request.organization.EditOrganizationReq;
import com.basics.api.request.organization.GroupOrganizationMemberReq;
import com.basics.api.request.organization.JoinOrganiztionByPhoneReq;
import com.basics.api.request.organization.OperateGroupReq;
import com.basics.api.response.organization.*;
import com.basics.api.response.socket.DeleteChannelData;
import com.basics.api.response.socket.MessageData;
import com.basics.api.response.socket.OpenData;
import com.basics.api.service.OrganizationApiService;
import com.basics.channel.entity.CyChannel;
import com.basics.channel.entity.CyChannelGroup;
import com.basics.channel.entity.CyChannelPermission;
import com.basics.channel.entity.CyChannelTopic;
import com.basics.common.exception.CustomException;
import com.basics.common.utils.AsyncUtil;
import com.basics.common.utils.StringUtils;
import com.basics.organization.entity.CyOrganization;
import com.basics.organization.entity.CyOrganizationGroup;
import com.basics.organization.entity.CyOrganizationPermission;
import com.basics.organization.entity.CyOrganizationUser;
import com.basics.user.entity.CyUser;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
public class OrganizationApiServiceImpl extends BaseApiService implements OrganizationApiService {

    @Override
    public OrganizationInfoData getOrganizationInfo(Long id, Long userId){
        CyOrganization organization = cyOrganizationService.getById(id);
        if(organization==null){
            throw new CustomException("组织信息不存在");
        }
        if(!cyOrganizationUserService.checkHasJoinOrganization(id,userId)){
            throw new CustomException("未加入该组织");
        }
        OrganizationInfoData data = new OrganizationInfoData();
        BeanUtils.copyProperties(organization,data);
        data.setInviteUrl("https://cyapi.dimoclub.com/#/pages/share/index?organizationId="+id);
        data.setIsCreateUser(cyOrganizationService.isCreateUser(userId,id));
        data.setMemberNum(cyOrganizationUserService.getJoinMemberNum(id));
        IPage<OrganizationMemberListData> memberPage = cyOrganizationUserService.selectJoinOrganizationMemberList(new Page<>(1,13),id,null);
        data.setMemberList(memberPage.getRecords());
        return data;
    }

    @Override
    public InvitionUrlData getInvitionUrl(Long id, Long userId){
        InvitionUrlData data = new InvitionUrlData();
        if(!cyOrganizationUserService.checkHasJoinOrganization(id,userId)){
            throw new CustomException("未加入该组织");
        }
        data.setInviteUrl("https://cyapi.dimoclub.com/#/pages/share/index?organizationId="+id);
        return data;
    }

    @Override
    public IPage<GroupOrganizationMemberListData> selectGroupOrganizationMemberList(GroupOrganizationMemberReq req, Long userId){
        if(!cyOrganizationUserService.checkHasJoinOrganization(req.getOrganizationId(),userId)){
            throw new CustomException("未加入该组织");
        }
        IPage<GroupOrganizationMemberListData> page =  cyOrganizationUserService.selectGroupOrganizationMemberList(new Page(req.getPageNum(),req.getPageSize()),req.getOrganizationId(),req.getSearchText());
        if(CollectionUtils.isNotEmpty(page.getRecords())){
            page.getRecords().forEach(v->{
                v.setGroupNum(cyOrganizationUserService.getGroupMemberNum(v.getGroupId()));
            });
        }
        return page;
    }

    @Override
    public GroupOrganizationData getGroupOrganization(Long id, Long userId){
        if(!cyOrganizationUserService.checkHasJoinOrganization(id,userId)){
            throw new CustomException("未加入该组织");
        }
        GroupOrganizationData data = new GroupOrganizationData();
        data.setAllMember(cyOrganizationUserService.getJoinMemberNum(id));
        data.setGroupList(cyOrganizationUserService.selectGroupList(id));
        return data;
    }

    @Override
    @Transactional
    public void saveGroupOrganization(EditOrganizationReq req, Long userId, Long id){
        if(!cyOrganizationService.isCreateUser(userId,id)){
            throw new CustomException("无权限操作");
        }
        CyOrganizationGroup group;
        if(StringUtils.isNotEmpty(req.getId())){
            group = cyOrganizationGroupService.getById(req.getId());
            if(StringUtils.isNotEmpty(req.getGroupName())){
                group.setGroupName(req.getGroupName());
            }
            if(StringUtils.isNotEmpty(req.getIconColor())){
                group.setIconColor(req.getIconColor());
            }
            cyOrganizationGroupService.updateById(group);
            cyOrganizationPermissionService.remove(new QueryWrapper<CyOrganizationPermission>().eq("group_id",group.getId()));
        }else{
            group = new CyOrganizationGroup();
            group.setGroupName(req.getGroupName());
            group.setIconColor(req.getIconColor());
            group.setDefaultFlag(false);
            group.setSortBy(cyOrganizationGroupService.count(new QueryWrapper<CyOrganizationGroup>()
                    .eq("organization_id", id))+1);
            group.setOrganizationId(id);
            cyOrganizationGroupService.save(group);

        }
        if(CollectionUtils.isNotEmpty(req.getPermissionList())){
            List<CyOrganizationPermission> permissionList = new ArrayList<>();
            req.getPermissionList().forEach(v->{
                if(GroupPermissionEnum.find(v.getPermission())==null){
                    throw new CustomException("权限标识不合法");
                }
                CyOrganizationPermission permission = new CyOrganizationPermission(group.getId(),v.getPermission());
                permissionList.add(permission);
            });
            cyOrganizationPermissionService.saveBatch(permissionList);
        }

    }

    @Override
    public EditOrganizationReq getEditOrganizationGroupInfo(String id,Long userId){
        CyOrganizationGroup group = cyOrganizationGroupService.getById(id);
        if(group==null){
            throw new CustomException("组织分组不存在");
        }
        EditOrganizationReq data = new EditOrganizationReq();
        data.setGroupName(group.getGroupName());
        data.setIconColor(group.getIconColor());
        data.setId(group.getId());
        data.setDefaultFlag(group.getDefaultFlag());
        data.setPermissionList(cyOrganizationPermissionService.selectGroupPermissionList(id));
        return data;
    }

    @Override
    @Transactional
    public void deleteGroupOrganization(String id,Long userId){
        CyOrganizationGroup group = checkGroup(id,userId);
        if(group.getDefaultFlag()){
            throw new CustomException("不能删除默认分组");
        }
        cyOrganizationGroupService.removeById(id);
        List<CyOrganizationUser> userList = cyOrganizationUserService.list(new QueryWrapper<CyOrganizationUser>().eq("group_id",id));
        if(CollectionUtils.isNotEmpty(userList)){
            CyOrganizationGroup defaultGroup = cyOrganizationGroupService.getDefaultGroup(group.getOrganizationId());
            if(defaultGroup!=null){
                userList.forEach(v->{
                    v.setGroupId(defaultGroup.getId());
                });
            }
            cyOrganizationUserService.updateBatchById(userList);
        }
    }

    @Override
    @Transactional
    public void removeGroupOrganization(OperateGroupReq req, Long userId){
        CyOrganizationGroup group =  checkGroup(req.getGroupId(),userId);
        if(group.getDefaultFlag()){
            throw new CustomException("不能移除默认分组");
        }
        CyOrganizationUser cyOrganizationUser = cyOrganizationUserService
                .getOne(new QueryWrapper<CyOrganizationUser>().eq("user_id",req.getUserId())
                        .eq("group_id",req.getGroupId()));
        if(cyOrganizationUser==null){
            throw new CustomException("该用户未加入该分组");
        }
        CyOrganizationGroup defaultGroup = cyOrganizationGroupService.getDefaultGroup(group.getOrganizationId());
        if(defaultGroup!=null){
            cyOrganizationUser.setGroupId(defaultGroup.getId());
        }
        cyOrganizationUserService.updateById(cyOrganizationUser);
    }

    @Override
    @Transactional
    public void addGroupOrganization(OperateGroupReq req, Long userId,Long organizationId){
        checkGroup(req.getGroupId(),userId);
        CyOrganizationUser cyOrganizationUser = cyOrganizationUserService
                .getOne(new QueryWrapper<CyOrganizationUser>().eq("user_id",req.getUserId())
                        .eq("organization_id",organizationId));
        if(cyOrganizationUser==null){
            throw new CustomException("该用户不在组织内");
        }
        if(StringUtils.isNotEmpty(cyOrganizationUser.getGroupId())){
            if(cyOrganizationUser.getGroupId().equals(req.getGroupId())){
                throw new CustomException("该用户已加入该分组");
            }
            throw new CustomException("该用户已加入其他分组");
        }
        cyOrganizationUser.setGroupId(req.getGroupId());
        cyOrganizationUserService.updateById(cyOrganizationUser);
    }

    @Override
    @Transactional
    public void saveChannel(CyChannel cyChannel, Long userId, Long organizationId){
        if(!cyOrganizationService.isCreateUser(userId,organizationId)){
            throw new CustomException("无权限操作");
        }
        cyChannel.setCreateUserId(userId);
        if(cyChannel.getId()==null){
            cyChannelService.save(cyChannel);
            CyChannelTopic topic = new CyChannelTopic();
            topic.setChannelId(cyChannel.getId());
            topic.setTopicName("话题");
            topic.setDefaultFlag(1);
            cyChannelTopicService.save(topic);

            CyChannelPermission cyChannelPermission = new CyChannelPermission();
            cyChannelPermission.setChannelId(cyChannel.getId());
            cyChannelPermission.setGroupIds("all");
            cyChannelPermission.setNeedAuth(false);
            cyChannelPermissionService.save(cyChannelPermission);

            CyChannelGroup cyChannelGroup = new CyChannelGroup();
            cyChannelGroup.setChannelId(cyChannel.getId());
            cyChannelGroup.setDefaultFlag(true);
            cyChannelGroup.setGroupName("默认分组");
            cyChannelGroup.setSortBy(0);
            cyChannelGroupService.save(cyChannelGroup);
            /**
             * 异步将所有用户加入该频道
             */
            AsyncUtil.runAsync(()->{
                cyChannelGroupUserService.addAllUserByOrganizationId(organizationId,cyChannel.getId());
                sendAllChannelMsg(cyChannel.getId(),organizationId,MessageEnum.PUSH_CHANNEL_INFO);
            });
        }else{
            cyChannelService.updateById(cyChannel);
        }

    }

    @Override
    @Transactional
    public void deleteChannel(Long channelId,Long userId,Long organizationId){
        if(!cyOrganizationService.isCreateUser(userId,organizationId)){
            throw new CustomException("无权限操作");
        }
        CyChannel cyChannel = cyChannelService.getById(channelId);
        if(cyChannel==null){
            throw new CustomException("频道不存在");
        }
        if(!cyChannel.getOrganizationId().equals(organizationId)){
            throw new CustomException("无权限操作");
        }
        cyChannel.setDelFlag(1);
        cyChannelService.updateById(cyChannel);

        AsyncUtil.runAsync(()->{
            sendAllChannelMsg(cyChannel.getId(),organizationId,MessageEnum.DELETE_CHANNEL);
        });
    }

    @Override
    public  void joinOrganizationByPhone(JoinOrganiztionByPhoneReq req){
        boolean flag = checkCode(req.getPhone(), null, req.getCode());
        if(!flag){
            throw new CustomException("验证码错误");
        }
        CyUser cyUser = cyUserService.getByPhone(req.getPhone());
        if(cyUser==null){
            cyUser = new CyUser();
            cyUser.setPhone(req.getPhone());
            cyUser.setSource("h5");
            cyUser.setNickName("用户"+req.getPhone());
            cyUserService.save(cyUser);
        }
        CyOrganizationUser organizationUser = cyOrganizationUserService.getByUserId(cyUser.getId(),req.getOrganizationId());
        if(organizationUser==null){
            CyOrganizationGroup group = cyOrganizationGroupService.getDefaultGroup(req.getOrganizationId());
            DefaultOrganizationInfoData defaultUser = cyOrganizationUserService.getDefaultOrganization(cyUser.getId());
            organizationUser = new CyOrganizationUser();
            organizationUser.setUserId(cyUser.getId());
            organizationUser.setOrganizationId(req.getOrganizationId());
            if(defaultUser!=null){
                organizationUser.setDefaultFlag(false);
            }else{
                organizationUser.setDefaultFlag(true);
            }

            if(group!=null){
                organizationUser.setGroupId(group.getId());
            }
            cyOrganizationUserService.save(organizationUser);
        }
        Long userId = cyUser.getId();
        AsyncUtil.runAsync(()->{
            cyChannelGroupUserService.addAllChannelByOrganizationId(req.getOrganizationId(),userId);
        });
    }

    @Override
    public void pushChannelMsg(Long organizationId,Long userId){
        OpenData data = new OpenData(cyChannelService.selectHomeChannelList(organizationId,userId)
                ,cyChannelMsgService.getUnReadMsgNumByOrganizationId(organizationId,userId));
        MessageData messageData = new MessageData(MessageEnum.PUSH_CHANNEL_ALL, JSONObject.parseObject(JSONObject.toJSONString(data)),organizationId);
        chatEndpoint.sendMessage(JSONObject.toJSONString(messageData),userId);
    }


    private CyOrganizationGroup checkGroup(String groupId,Long userId){
        CyOrganizationGroup group = cyOrganizationGroupService.getById(groupId);
        if(group==null){
            throw new CustomException("组织分组不存在");
        }
        if(!cyOrganizationService.isCreateUser(userId,group.getOrganizationId())){
            throw new CustomException("无权限操作");
        }
        return group;
    }
}
